﻿using System;
using System.Collections.Generic;
using System.Linq;
using FlanProjectData.Helpers;
using FlanProjectData.Maps;
using FlanProject.Combats;
using FlanProjectData.GameObjects;
using FlanProjectData.Managers;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.Xml.Serialization;  // XmlSerialiser
using System.IO;
using FlanProjectData.Characters; // pour Stream

namespace FlanProject.ScreenMenu
{
    public class GameScreen : InterfaceScreen
    {
        enum State
        {
            FIGHT,
            POPUPDRAW,
            OTHERSCREEN,
            INGAME,
        }

        //#region Debug Attributs

        //NonPlayableCharacter npc = new NonPlayableCharacter();

        //#endregion


        #region Attributs

        private static Logger logger = new Logger("GameScreen", Log_Type.DEBUG);

        //permet de savoir si l'inventaire a été fermé ou pas.
        bool inventaireClosed=false;

		// Game is over or not
		bool gameOver = false;

        // The current to be draw on the screen
        private Map currentMap;

        // Define the session of the fight session
        // It will be load when a fight is declared
        private bool isInFight = false;

        // Define the Team who evolute on the map
        // private Party Team;

        // List of PopUP
        // They'll be draw in the draw method.
        private List<PopupComponent> lstOfPopUp;

        // Time manager
        private TimeSpan interval = new TimeSpan(1500000);	// 0.1s
        private TimeSpan lastUpdate;
        private GameTime gametime;

        // Get state of the gamescreen
        private State currentWindowState;

        // get the name of the save
        private String nameSave;

        #endregion



        private PopupComponent popupInformation;

        #region Ctors

        public GameScreen(GameTime gt, String save)
        {
            this.Visible = true;
            this.imChild = null;
            this.GameScreenIsOn = true;
            this.gametime = gt;
            this.currentWindowState = State.INGAME;
            this.nameSave = save;
            //this.Team = new Party(); // new party;








            //int i = 0;

            /*this.lstMenuEntrySelectable.Add(new MenuEntry("Quit Game",
                new Vector2(((float)windowsWidth * widthDistanceButton),
                    ((float)windowsHeight * heightDistanceButton) + ((float)windowsHeight * (distanceBetween2Button * i++))),
                new Vector2((float)windowsWidth * widthPercentButton,
                    (float)windowsHeight * heightPercentButton)));

            this.lstMenuEntrySelectable[i - 1].Selected += this.ExitScreen;*/

        }

        #endregion

        #region Drawing manager

        public override void Initialize()
        {
            logger.Debug("Initialize");
            CombatEngine.Initialize();
            base.Initialize();
        }

        public override void LoadContent(ContentManager cm)
        {
            try
            {
                this.Content = cm;

                //Configure the timer 
                this.lastUpdate = this.gametime.ElapsedGameTime;

                //this.background = new Rectangle();
                //this.calcScaleBackground(windowsHeight, windowsWidth);
                this.currentMap = cm.Load<Map>(@"Data/Maps/World1");
                this.currentMap.AddSaveName(this.nameSave);
                this.currentMap.ScreenCenter = new Vector2(windowsWidth / 60, windowsHeight / 60);
                this.currentMap.LoadContent(cm);
                this.currentMap.evt += CatchADrawableMessage;

                CombatEngine.LoadPartyMembers(currentMap.Team);
                CombatEngine.LoadContent(cm);

                //this.Team.LoadContent(cm);
                //this.Team.save();
                //loadingParty();
                //this.currentMap.setPosition(this.Team.getPosition());


                //temp
                // this.itemTemp = new Item("menottes SM");
                // this.Team.addItem(itemTemp);


                // Add the party to the map
                // this.currentMap.AddParty(this.Team);

                base.LoadContent(cm);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public override void Draw(SpriteBatch sb)
        {
            switch (this.currentWindowState)
            {
                case State.POPUPDRAW:
                    this.currentMap.Draw(sb, this.gametime);
                    base.Draw(sb);
                    this.popupInformation.Draw(sb);
                    break;
                case State.FIGHT:
                    CombatEngine.Draw(sb, gametime);
                    break;
                case State.OTHERSCREEN:
                    base.Draw(sb);
                    break;
                case State.INGAME:
                    this.currentMap.Draw(sb, this.gametime);
                    base.Draw(sb);
                    break;
            }
        }

        public override void Update()
        {
            switch (this.currentWindowState)
            {
                case State.POPUPDRAW:
                    this.popupInformation.Update();
                    if (popupInformation.IsExiting)
                    {
                        this.currentWindowState = State.INGAME;
                        this.IsFocused = true;
                        this.popupInformation = null;
						// Close gameScreen
						if (this.gameOver)
						{
							this.IsExiting = true;
						}
                    }

                    break;
                case State.FIGHT:
                    CombatEngine.Update(gametime);
                    //End of the fight
                    if (CombatEngine.AreMonstersDefeated() || CombatEngine.ArePlayersDefeated())
                    {
                        logger.Info("Fight is finished");
                        this.currentWindowState = State.INGAME;
                        this.currentMap.FightEvent = false;
                        this.isInFight = false;
                        this.IsFocused = true;
                        this.currentMap.LootItem = true;

                        CombatEngine.Reset();
                    }
					// All players are dead
					if (CombatEngine.ArePlayersDefeated())
					{
						this.IsFocused = false;
						this.popupInformation = new PopupComponent("GAME OVER", 1,
							new Vector2(100, 400));
						this.popupInformation.LoadContent(this.Content);
						this.popupInformation.BackgroundColor = Color.Black;
						this.popupInformation.ForegroundColor = Color.Red;
						this.popupInformation.Visible = true;
						this.currentWindowState = State.POPUPDRAW;

						this.gameOver = true;
					}
                    break;
                case State.OTHERSCREEN:

                    if (this.inventaireClosed) // on recupere les changements dans l'inventaire
                    {
                        this.currentMap.Team = ((InventoryScreen)this.imChild).Team;
                        this.inventaireClosed = false;
                    }

                    if (imChild != null && imChild.IsExiting)
                    {
                        

                        this.currentWindowState = State.INGAME;
                        this.isInFight = false;
                        this.imChild.Visible = false;
                        this.IsFocused = true;
                        this.imChild = null;
                        

                    }
                    else if (imChild != null)
                    {
                        //this.imChild.Update();
                    }
                    else
                    {
                        this.currentWindowState = State.INGAME;
                    }
                    break;
                case State.INGAME:
                    if (TimeActionPossible())
                        currentMap.Update();

                    if (this.currentMap.FightEvent)
                    {
                        logger.Debug("Fight launch by map");
                        // Initialize the fight

                        this.IsFocused = false;
                        this.isInFight = true;
                        this.currentWindowState = State.FIGHT;
                    }

                    if (isExitingGame) // si on veut fermer le jeux
                    {
                        this.ExitScreen();
                        isExitingGame = false;
                    }

                    if (savingGame) // si on veut sauvegarder
                    {
                        currentMap.Team.save(nameSave);
                        isExitingGame = false;
                        savingGame = false;

                        string message = "";
                        message += "Game saved !";

                        this.IsFocused = false;
                        this.popupInformation = new PopupComponent(message, 1,
                            new Vector2(100, 100));
                        this.popupInformation.LoadContent(this.Content);
                        this.popupInformation.Visible = true;
                        this.currentWindowState = State.POPUPDRAW;

                    }
                    


                    break;
            }
            this.lastUpdate += this.gametime.ElapsedGameTime;
            base.Update();
        }

        #endregion

        #region HandleInput

        public override void HandleInput()
        {
            switch (this.currentWindowState)
            {
                case State.INGAME:
                    /* Movement on map */
                    /* if (this.TimeActionPossible())
                    {
                        currentMap.Update();
                    } */

                    // Validation an quest action if it is possible
                    if (InputManager.IsActionTriggered(InputManager.Action.Ok))
                    {
                        //TODO implement here
                    }
                    else if (InputManager.IsActionTriggered(InputManager.Action.Exit))
                    {
                        //logger.Debug("Exit GameScreen");
                        //this.IsExiting = true;
                        logger.Info("Ouverture de l'ecran de pause");
                        this.imChild = new PauseScreen();
                        this.imChild.LoadContent(this.Content);
                        this.imChild.Visible = true;
                        this.Visible = false;
                        this.currentWindowState = State.OTHERSCREEN;
                    }
                    else if (InputManager.IsKeyTriggered(Keys.Q))
                    {
                        //TODO Remove after testing
						string message = "";
						if(currentMap.Team.currentQuest != null)
							message = "[In Progress] - " + currentMap.Team.currentQuest.QuestName + '\n';
						message += "[Quest Done]\n";

						foreach (Quest q in currentMap.Team.questDone)
						{
							message += (q.QuestName + '\n'); 
						}

						if (message == "") message = "No quest at this moment";

                        this.IsFocused = false;
                        this.popupInformation = new PopupComponent(message, 3,
                            new Vector2(100, 400));
						this.popupInformation.LoadContent(this.Content);
						this.popupInformation.BackgroundColor = Color.Transparent;
						this.popupInformation.ForegroundColor = Color.LightGray;
                        this.popupInformation.Visible = true;
                        this.currentWindowState = State.POPUPDRAW;
                        logger.Info("Touche appuye Q");
                    }
                    else if (InputManager.IsKeyTriggered(Keys.I))
                    {
                        logger.Info("InventoryScreen is openning");
                        var team = this.currentMap.Team;
                        inventaireClosed = true;
                        this.imChild = new InventoryScreen(ref team);
                        this.imChild.LoadContent(this.Content);
                        this.imChild.Visible = true;
                        this.Visible = false;
                        this.currentWindowState = State.OTHERSCREEN;
                        // Console.WriteLine(((InventoryScreen)imChild).Team.MovementSpeed);
                        // logger.Debug("taille de l'inventaire:"+this.Team.Inventory.lstItems.Count);
                    }
                    /*
                else if (InputManager.IsKeyTriggered(Keys.S))
                {
                    logger.Debug("on sauvegarde");
                    this.Team.save(this.nameSave);
                        

                }
                      */
                    break;
                case State.POPUPDRAW:
                    // Done in the popupcomponent.update();
                    //this.popupInformation.HandleInput();
                    break;
                case State.OTHERSCREEN:
                    this.imChild.HandleInput();

                    break;
            }
        }

        #endregion

        private bool TimeActionPossible()
        {
            bool coderet = false;
            float timePassed = this.lastUpdate.Milliseconds;
            lastUpdate += gametime.ElapsedGameTime;
            if (lastUpdate >= interval)
            {
                coderet = true;
                lastUpdate = TimeSpan.Zero;
            }
            return coderet;
        }

        private void CatchADrawableMessage(object sender, EventArgs e)
        {
            logger.Debug("Receive event, Someone demand me to draw a message");
            if (sender is NonPlayableCharacter && e is Event)
            {
                string msg = ((Event)e).msg;
                this.popupInformation = new PopupComponent(msg, 3, new Vector2(10, 400));
                this.popupInformation.LoadContent(this.Content);
                this.popupInformation.Visible = true;
                this.currentWindowState = State.POPUPDRAW;
            }
            else
            {
                logger.Warn("Event problem, NPC or Event not exist");
            }
        }
    }
}
